﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;

namespace 自动点击鼠标
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public enum KeyModifiers //组合键枚举
        {
            None = 0,
            Alt = 1,
            Control = 2,
            Shift = 4,
            Windows = 8
        }
        /*
         * RegisterHotKey函数原型及说明：
         * BOOL RegisterHotKey(
         * HWND hWnd,         // window to receive hot-key notification
         * int id,            // identifier of hot key
         * UINT fsModifiers, // key-modifier flags
         * UINT vk            // virtual-key code);
         * 参数 id为你自己定义的一个ID值
         * 对一个线程来讲其值必需在0x0000 - 0xBFFF范围之内,十进制为0~49151
         * 对DLL来讲其值必需在0xC000 - 0xFFFF 范围之内,十进制为49152~65535
         * 在同一进程内该值必须唯一参数 fsModifiers指明与热键联合使用按键
         * 可取值为：MOD_ALT MOD_CONTROL MOD_WIN MOD_SHIFT参数，或数字0为无，1为Alt,2为Control，4为Shift，8为Windows
         * vk指明热键的虚拟键码
         */
        /// <summary>
        /// 申明API函数，注册热键
        /// </summary>
        /// <param name="hWnd">Handle为当前窗口的句柄,继续自Control.Handle,Control为定义控件的基类</param>
        /// <param name="id">id为你自己定义的一个ID值，十进制为0~49151</param>
        /// <param name="fsModifiers">热键联合使用按键整数</param>
        /// <param name="vk">Keys对象</param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool RegisterHotKey(
         IntPtr hWnd, // handle to window 
         int id, // hot key identifier 
         uint fsModifiers, // key-modifier options 
         Keys vk // virtual-key code 
        );
        /// <summary>
        /// 申明API函数，取消热键
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool UnregisterHotKey(
         IntPtr hWnd, // handle to window 
         int id // hot key identifier 
        );

        [System.Runtime.InteropServices.DllImport("User32")]
        public extern static void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);

        [System.Runtime.InteropServices.DllImport("User32")]
        public extern static void SetCursorPos(int x, int y);

        [System.Runtime.InteropServices.DllImport("User32")]
        public extern static bool GetCursorPos(out POINT p);

        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
        public struct POINT
        {
            public int X;
            public int Y;
        }

        public enum MouseEventFlags
        {
            Move = 0x0001,
            LeftDown = 0x0002,
            LeftUp = 0x0004,
            RightDown = 0x0008,
            RightUp = 0x0010,
            MiddleDown = 0x0020,
            MiddleUp = 0x0040,
            Wheel = 0x0800,
            Absolute = 0x8000
        }

        static decimal count = 1;
        static Point CursorPosition_old = new Point(0, 0);
        /// <summary>
        /// 标记点击什么按钮
        /// </summary>
        static byte sid = 0;

        #region 自动点击左键的方法，传入鼠标坐标

        /// <summary>
        /// 自动点击左键的方法，传入鼠标坐标
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void AutoLeftClick(int x, int y)
        {
            POINT p = new POINT();
            GetCursorPos(out p);
            try
            {
                SetCursorPos(x, y);
                mouse_event((int)(MouseEventFlags.LeftDown | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
                mouse_event((int)(MouseEventFlags.LeftUp | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
            }
            finally
            {
                SetCursorPos(p.X, p.Y);
            }
        }

        #endregion

        #region 自动点击右键的方法，传入鼠标坐标

        /// <summary>
        /// 自动点击右键的方法，传入鼠标坐标
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        private void AutoRightClick(int x, int y)
        {
            POINT p = new POINT();
            GetCursorPos(out p);
            try
            {
                SetCursorPos(x, y);
                mouse_event((int)(MouseEventFlags.RightDown | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
                mouse_event((int)(MouseEventFlags.RightUp | MouseEventFlags.Absolute), 0, 0, 0, IntPtr.Zero);
            }
            finally
            {
                SetCursorPos(p.X, p.Y);
            }
        }

        #endregion



        #region 窗体加载注册按钮热键（快捷键）

        private void Form1_Load(object sender, EventArgs e)
        {
            this.button1.BackColor = Color.Yellow;
            RegisterHotKey(Handle, 100, 2 | 1, Keys.PageUp);//这时热键为Ctrl+Alt+PageUp，用于点击左键
            RegisterHotKey(Handle, 200, 2 | 1, Keys.PageDown);//这时热键为Ctrl+Alt+PageDown，用于点击右键 
        }

        #endregion

        #region 窗体退出卸载快捷键

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnregisterHotKey(Handle, 100);//卸载第1个快捷键
            UnregisterHotKey(Handle, 200); //缷载第2个快捷键

        }

        #endregion

        #region 点击颜色改变

        private void button1_MouseDown(object sender, MouseEventArgs e)
        {
            button1.BeginInvoke(new Action(() =>
            {
                if (button1.BackColor == Color.Yellow)
                {
                    this.button1.BackColor = Color.Blue;
                    return;
                }
                if (button1.BackColor == Color.Blue)
                {
                    this.button1.BackColor = Color.Yellow;
                }
            }));
        }

        #endregion

        #region 1.点击开始执行：重写WndProc()方法，通过监视系统消息，来调用过程

        /// <summary>
        /// 1.点击开始执行：重写WndProc()方法，通过监视系统消息，来调用过程
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)//监视Windows消息
        {
            const int WM_HOTKEY = 0x0312;//如果m.Msg的值为0x0312那么表示用户按下了热键
            switch (m.Msg)
            {
                case WM_HOTKEY:
                    ProcessHotkey(m);//按下热键时调用ProcessHotkey()函数
                    break;
            }
            base.WndProc(ref m); //将系统消息传递自父类的WndProc
        }

        #endregion

        #region 2.按下设定的键时调用该函数

        /// <summary>
        /// 2.按下设定的键时调用该函数
        /// </summary>
        /// <param name="m"></param>
        private void ProcessHotkey(Message m)
        {
            IntPtr id = m.WParam; //IntPtr用于表示指针或句柄的平台特定类型
            //MessageBox.Show(id.ToString());
            string _sid = id.ToString();
            switch (_sid)
            {
                case "100":
                    sid = 1;
                    //MessageBox.Show("调用A函数，开始点击左键");
                    this.label4.Text = "正在点击：左键";
                    Init_RuningValue();

                    break;
                case "200":
                    sid = 2;
                    this.label4.Text = "正在点击：右键";
                    //MessageBox.Show("调用B函数，开始点击右键");
                    Init_RuningValue();
                    break;
            }
        }

        #endregion



        #region 3.初始化执行参数

        ///// <summary>
        ///// 3.初始化执行参数
        ///// </summary>
        //private void Init_RuningValue()
        //{
        //    count = 1;
        //    CursorPosition_old = Cursor.Position;//取得当前鼠标位置
        //    timer1.Enabled = true;//开始
        //    string timeSpace = this.textBox1.Text.Trim();//设置的时间间隔
        //    int timeSpace_m = 1;//鼠标点击间隔，毫秒
        //    if (!string.IsNullOrWhiteSpace(timeSpace))
        //    {
        //        timeSpace_m = Convert.ToInt32(timeSpace);
        //    }
        //    timer1.Interval = timeSpace_m;
        //}

        /// <summary>
        /// 是否继续点击
        /// </summary>
        static bool working = true;

        /// <summary>
        /// 3.初始化执行参数
        /// </summary>
        /// 2018-12-21 20:34:35 更新，优化性能
        private void Init_RuningValue()
        {
            working = true;
            count = 0;
            CursorPosition_old = Cursor.Position;//取得当前鼠标位置
            string timeSpace = this.textBox1.Text.Trim();//设置的时间间隔
            int timeSpace_m = 0;//鼠标点击间隔，毫秒
            if (!string.IsNullOrWhiteSpace(timeSpace))
            {
                timeSpace_m = Convert.ToInt32(timeSpace);
            }
            //if (!this.checkBox1.Checked)
            //{
            //    timeSpace_m = 1;
            //}
            Task.Run(() =>
        {
            while (working)
            {
                MoseClick();
                //Thread.SpinWait(timeSpace_m);

                //高速模式
                if (this.checkBox1.Checked)
                {
                    if (timeSpace_m > 0)
                    {
                        //高速循环间隔，取决于cpu的执行速度
                        SpinWait.SpinUntil(() => true, timeSpace_m);
                    }
                }
                else
                {
                    //低速循环间隔
                    Thread.Sleep(timeSpace_m);
                }
            }
        });
        }

        #endregion

        #region 4.执行自动点击 void timer1_Tick(object sender, EventArgs e)

        //private void timer1_Tick(object sender, EventArgs e)
        //{
        //    //Task.Run(()=>MoseClick(sid));
        //    //MoseClick(sid);
        //    Task.Run(() => MoseClick());
        //}
        #endregion

        #region 5.自动点击，鼠标位置改变停止点击

        //private void MoseClick(object objsid)
        private void MoseClick()
        {
            //存放着当前鼠标的位置坐标
            Point CursorPosition_new = Cursor.Position;
            if (CursorPosition_new == CursorPosition_old)
            {
                if (sid == 1)//点击左键
                {
                    AutoLeftClick(CursorPosition_new.X, CursorPosition_new.Y);
                }
                else if (sid == 2)//点击右键
                {
                    AutoRightClick(CursorPosition_new.X, CursorPosition_new.Y);
                }
                //this.textBox2.Text = (count++).ToString();
                count++;
                Task.Run(() =>
                {
                    this.textBox2.BeginInvoke(new Action(() =>
                    {
                        this.textBox2.Text = count.ToString();
                    }));
                });
            }
            else
            {
                //位置改变了，不执行继续点击了
                working = false;
            }
        }

        //private void MoseClick()
        //{
        //    //string _sid = objsid.ToString();   
        //    //存放着当前鼠标的位置坐标
        //    Point CursorPosition_new = Cursor.Position;
        //    if (CursorPosition_new == CursorPosition_old)
        //    {
        //        if (sid == 1)//点击左键
        //        {
        //            AutoLeftClick(CursorPosition_new.X, CursorPosition_new.Y);
        //        }
        //        else if (sid == 2)//点击右键
        //        {
        //            AutoRightClick(CursorPosition_new.X, CursorPosition_new.Y);
        //        }
        //        //this.textBox2.Text = (count++).ToString();
        //        Task.Run(() => {
        //            this.textBox2.BeginInvoke(new Action(() => {
        //                this.textBox2.Text = (count++).ToString();
        //            }));
        //        });
        //    }
        //    else
        //    {
        //        timer1.Enabled = false;//结束点击  
        //    }
        //}

        #endregion













    }
}
